package me.lcc.demo.pdf.web.controller;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;

/**
 * 打印组装
 * @author LiuChao
 *
 */
@Slf4j
@RestController
@RequestMapping("/demo/pdf")
public class ItextDemoController {
	private Configuration freemarkerCfg = null;
    /**
     * 模板所在路径
     */
//	@Value("${custom.print.templatPath}")
	private String templatPath;
	/**
	 * 字体所在路径-解决中文无法显示问题
	 */
//	@Value("${custom.print.fontPath}")
	private String fontPath;
	/**
	 * 生成的pdf路径
	 */
//	@Value("${custom.print.descPath}")
	private String descPath;

	/**
	 * 初始化模板工厂
	 */
	public void initFreemarkerCfg(){
        freemarkerCfg = new Configuration(Configuration.getVersion());
        
        try {
        	descPath = descPath == null ? "/temp/demo-pdf/desc/" : descPath;
        	fontPath = fontPath == null ? "/temp/demo-pdf/font/simfang.ttf" : fontPath;
        	templatPath = templatPath == null ? "/temp/demo-pdf/templat/" : templatPath;
        	
        	freemarkerCfg.setDirectoryForTemplateLoading(new File(templatPath));
        } catch (IOException e) {
        	log.error("ERR: InitFreemarkerCfg报错", e);
        }
    }
	
	/**
	 * 小票示例-通过map构建参数
	 * 
<pre>
  <table>
	<tr><td>姓名:</td><td>${name}</td></tr>
	<tr><td>性别:</td><td>${sex}</td></tr>
	<tr><td>日期:</td><td>${date}</td></tr>
	<tr><td>就诊医师:</td><td>${doctor}</td></tr>
	<tr><td>就诊顺序:</td><td>${order}</td></tr>
	<tr><td>诊室:</td><td>${clinic}</td></tr>
	<tr><td>服务费金额:</td><td>${fees}</td></tr>
	<tr><td>支付方式:</td><td>${payType}</td></tr>
	<tr><td>打印时间:</td><td>${printTime}</td></tr>
  </table>
</pre>
	 * @return
	 * @throws DocumentException 
	 * @throws IOException 
	 * @throws TemplateException 
	 */
	@RequestMapping("/receipts")
	public void createReceiptsFreemarkerPDF(@RequestParam Map<String,String> param, HttpServletResponse response) throws IOException, DocumentException, TemplateException {
		String[] keys = {"name", "sex", "date", "doctor", "order", "clinic", "fees", "payType", "printTime"};
		for (String key : keys) {
			if(!param.containsKey(key)) {
				param.put(key, "N/A");
			}
		}
		
		 String content = createFreemarkerPDF(param, "freemarker_receipts.html");
		 createPDF(content, new Document(new Rectangle(224f, 298f), 12, 12, 12, 12), response);
	}
	
	/**
	 * 智慧处方-通过json构建pdf
	 * @param jsonstr
	 * @param response
	 * @throws TemplateException 
	 * @throws IOException 
	 * @throws DocumentException 
	 */
	@RequestMapping("/wisdom_prescription")
	public void createReceiptsFreemarkerPDF(HttpServletResponse response) throws IOException, TemplateException, DocumentException {
		String prescription = "{\"diseaseTarget\":[],\"health\":{\"healthJson\":{\"dangerFactorContent\":\"饮食不控制：\",\"diseaseList\":[],\"content\":\"目前您的体重超出了界限，建议您适当控制饮食、增加运动量，将体重逐步恢复到正常的体重范围：58.5 ~ 71.5 kg，您的理想体重约为65.0 kg。\",\"dangerFactorList\":\"$$超重\"},\"diagnoseJson\":{},\"targetJson\":{\"bloodPressure\":\"血压：140 / 90 mmHg 以内\",\"bloodFat\":\"血脂： LDL-C <3.4 mmol/L； HDL-C >1.0 mmol/L；TC <4.5 mmol/L ；TG <1.7 mmol/L\",\"start\":\"经过个体化分析，适合您的相关指标控制范围，推荐如下\",\"end\":\"上述目标仅供参考，如果合并其它疾病，相关指标可适当放宽。\",\"bloodGlucose\":\"血糖：空腹血糖 4.4-7.0 mmol/L；餐后血糖 <10 mmol/L；随机血糖 <10 mmol/L；糖化血红蛋白<8.0%\"},\"physiqueJson\":{},\"riskJson\":{\"content\":\"当前您的  空腹血糖、高密度脂蛋白胆固醇 控制不达标。<br/>目前您的收缩压 120.0 / 80.0 mmHg，属于 正常血压 ，心血管危险分层：低危 。<br/>动脉粥样硬化性心血管疾病（ASCVD）发病危险分层： 10年危险：低危(<5%) 。<br/>\"}},\"list\":[{\"foodGood\":{},\"diseaseGuidelineList\":[],\"foodBad\":{},\"fuBiao\":true,\"type\":\"营养膳食处方\",\"foodWeek\":{\"status\":false},\"content\":[{\"title\":\"三餐热量\",\"contentList\":[{\"hasTitle\":false,\"title\":\"\",\"content\":[\"通过分析当前的身体指标，您每天所需要的总热量为：1950千卡，约  22 份食物。\",\"建议摄入热量的三餐分布为：早餐  585 千卡（约 7 份食物），午餐  780千卡（约 9 份食物），晚餐 585 千卡（约 7 份食物）。\"]},{\"hasTitle\":true,\"title\":\"加餐提示\",\"content\":[\"对于糖尿病或老年人群，建议少食多餐，或根据实际情况适当增加用餐次数：时间于两次正餐之间，约上午10点或下午3点，加餐热量占每日总热量的5~10%， 约为 195 千卡（约 2.2 份食物）。\\n注意：若加餐，则要从三次正餐的食物总量中，减去加餐的食物份数。\"]},{\"hasTitle\":false,\"title\":\"\",\"content\":[\"【注释：每份食物热量为90千卡，食物选择参考《食物交换份》附表，可由膳食原则与个人喜好，自主搭配。】\"]}]},{\"title\":\"营养分布\",\"contentList\":[{\"hasTitle\":true,\"title\":\"三大营养素为：\",\"content\":[\"蛋白质、脂肪、碳水化合物，均能给机体提供热量，人体每天须摄入适量的三类营养素，才能达到热量营养素平衡，满足身体的营养需求。根据计算，您每天所需三大营养素的热量和克数为：\"]},{\"hasTitle\":false,\"title\":\"\",\"content\":[\"蛋白质：< 293   千卡>，约 73 克。脂肪：< 488 千卡>约 54 克，碳水化合物：< 1170 千卡> 约 293 克。\"]}]},{\"title\":\"饮食原则\",\"contentList\":[{\"hasTitle\":true,\"title\":\"热量原则\",\"content\":[\"控制每日饮食总热量，保持能量平衡、健康体重。您的理想体重范围约为 58.5 ~ 71.5 kg。\",\"当前您的体重超过了正常范围，建议您减重不宜过快，食品中蛋白质所占比例可稍多些，一般采用低脂饮食(<40g/天)，同时需补充维生素和无机盐。\",\"蔬菜可作为充饥食物，多吃汆、清蒸、煮、拌的蔬菜，忌用高油脂食物。傍晚或临睡前不宜进食较多食物。推荐富含纤维素食物摄入。\"]},{\"hasTitle\":true,\"title\":\"种类原则\",\"content\":[\"食物多样化，谷类为主，定时定量饮食。 每天的膳食应包括谷薯类、蔬菜水果类、畜禽鱼蛋奶类、大豆坚果类等食物。平均每天摄入12种以上食物，每周25种以上。\"]}]},{\"title\":\"食物多样\",\"contentList\":[{\"hasTitle\":true,\"title\":\"谷薯类\",\"content\":[\"建议每天摄入谷薯类食物250~400g（约半斤~八两），其中全谷物和杂豆类100~200g（约2~4两），薯类50~100g（约1~2两）。\"]},{\"hasTitle\":true,\"title\":\"菜果类\",\"content\":[\"餐餐有蔬菜：保证每天摄入新鲜蔬菜500g（约1斤），深色蔬菜应占1/2。尽量生食，烹调采用先洗后切，急火快炒、开汤下菜、炒好即食原则。\",\"天天吃水果：每天可摄入200g新鲜当季水果，果汁不能代替鲜果。水果摄入时间：两次正餐之间（如上午10点、下午3点），作为加餐食用，餐前或餐后不要立即吃水果。\"]},{\"hasTitle\":true,\"title\":\"肉蛋类\",\"content\":[\"鱼、禽、蛋、瘦肉摄入都要适量。每周摄入量：鱼、畜禽肉、蛋类，各280~525g（每类约半斤~1斤）。\\n平均每天摄入总量120~200g（约2~4两）。优先选择鱼和瘦肉，吃鸡蛋不弃蛋黄。少吃肥肉、烟熏和腌制肉制品、减少油炸。\"]},{\"hasTitle\":true,\"title\":\"其它\",\"content\":[\"摄入各种各样的奶制品，相当于每天液态奶300克。可选择无糖酸奶。经常吃大豆或豆制品，适量吃坚果。\",\"足量饮水，建议成人每天饮水7~8杯（1500-1700ml），提倡白开水和茶水，不喝或少喝含糖高的饮料。\",\"培养清淡饮食习惯，少油少盐，建议每日食盐不超过6g。不要求摄入添加糖，若需要摄入建议控制在25g以内。\"]}]},{\"title\":\"注意事项\",\"contentList\":[{\"hasTitle\":true,\"title\":\"老年人群\",\"content\":[\"需注意的膳食原则：\\n少量多餐细软，预防营养缺乏。主动足量饮水，积极户外活动。\\n延缓肌肉衰减，维持适宜体重。摄入充足食物，鼓励陪伴进餐。\"]}]}]},{\"diseaseGuidelineList\":[],\"type\":\"健康运动处方\",\"content\":[{\"title\":\"运动指导\",\"contentList\":[{\"hasTitle\":true,\"title\":\"运动强度：\",\"content\":[\"中等强度。主观感受为：有点吃力，运动时可交谈，伴轻度的喘息。\",\"根据您的身体情况，分析出适合您的运动心率范围为 92 次/分钟。\"]},{\"hasTitle\":true,\"title\":\"提示：\",\"content\":[\"运动中的适宜心率，需要根据：健康状态、运动环境、季节、心情等实际情况灵活掌握，必要时运动强度、运动时间均要相应降低，心率指标亦相应降低，以保证身体健康安全。\"]},{\"hasTitle\":true,\"title\":\"一周运动总时长\",\"content\":[\"老年人群，建议咨询医生根据具体身体情况确定每周运动总时长。\"]},{\"hasTitle\":true,\"title\":\"运动时机：\",\"content\":[\"尽量在餐后60-90分钟进行，避免餐前空腹状态下运动。清晨6～10点是心脑血管事件的高发时段，最好选择下午或傍晚进行锻炼。\"]}]},{\"title\":\"特别注意\",\"contentList\":[{\"hasTitle\":false,\"title\":\"\",\"content\":[\"经过运动喜好分析，您当前：缺少有氧运动项目、缺少抗阻力运动、缺少柔韧性练习 \"]},{\"hasTitle\":true,\"title\":\"建议有氧运动\",\"content\":[\"为了促进或保持健康/体适能，推荐给大多数成年人的有氧运动建议。\"]},{\"hasTitle\":true,\"title\":\"有氧运动频率及时间\",\"content\":[\"每周进行3~5次中等强度的有氧运动，每次最好30分钟以上。\\n起始有氧运动，项目推荐：步行、慢跑、骑自行车、健身操、太极拳、游泳等。\"]},{\"hasTitle\":true,\"title\":\"抗阻运动说明\",\"content\":[\"增加抗阻力运动，适宜的抗阻运动应是对全身主要大肌群（包括：胸部，肩部，背部，腰部，腹部，臀部和下肢）进行训练。\"]},{\"hasTitle\":true,\"title\":\"抗阻运动频率\",\"content\":[\"频率为每周2~3次，同一肌群的练习时间应至少间隔48小时。\"]},{\"hasTitle\":true,\"title\":\"柔韧性运动提示\",\"content\":[\"研究表明，所有年龄段的人都可以通过柔韧性练习提高关节的活动度、稳定性和平衡性，使身体获益。\\n提示：当肌肉温度升高后，再进行柔韧性练习的效果会更好。\"]},{\"hasTitle\":true,\"title\":\"柔韧性运动频率与时间\",\"content\":[\"推荐运动：侧部压腿、坐位体前屈、静力性拉伸等，每次拉伸在到达拉紧或轻微不适时，应保持10~30秒，每一个部位可以重复2~4次，累计60秒。\\n频率为每周2~3次，强度：自觉肌肉绷紧或轻微不适。\"]},{\"hasTitle\":true,\"title\":\"老年人群提示\",\"content\":[\"老年人群运动时，随时携带救助卡，卡片上注明自己的姓名、疾病诊断、病情、家人联络方式，以及家庭医生的联络电话等信息，并随身携带。\"]}]}]},{\"diseaseGuidelineList\":[],\"type\":\"烟酒节制处方\",\"content\":[{\"title\":\"吸烟情况\",\"contentList\":[{\"hasTitle\":false,\"title\":\"\",\"content\":[\"您   [不吸烟情况]，非常好，请继续保持！同时，生活中尽量避免被动吸烟。\"]}]},{\"title\":\"饮酒情况\",\"contentList\":[{\"hasTitle\":false,\"title\":\"\",\"content\":[\"您不饮酒，非常好，请继续保持！现代医学证明，饮酒对健康没有益处。\"]}]}]},{\"diseaseGuidelineList\":[],\"type\":\"心理减压处方\",\"content\":[{\"title\":\"生活方面建议\",\"contentList\":[{\"hasTitle\":true,\"title\":\"舒缓心情的方法\",\"content\":[\" 如出现心情不好，烦躁易怒等情况，尝试进行深呼吸，闭上嘴，用鼻深吸气-屏住呼吸-深呼吸，使呼气的时间是吸气时间的2倍；肌肉放松法：拉紧肌肉（5-10秒），然后放松可以是面部，比如咬牙，也可以是肢体肌肉；聆听舒缓的音乐，曲调缓慢或者没有歌词的纯音乐。  \"]},{\"hasTitle\":false,\"title\":\"\",\"content\":[\"如发现异常及时就医，近2周内，出现睡眠、情绪、兴趣及人际关系方面的无法解释的变化，请及时就诊于心身医学科。定期体检筛查：每年到医院完成一次认知功能和抑郁症筛查。\"]}]}]},{\"diseaseGuidelineList\":[],\"type\":\"中医调摄处方\",\"content\":[]}]}";

		Map<String,Object> param = new HashMap<String, Object>();
		param.put("peopleName", "张三");
		param.put("doctorName", "李四");
		param.put("reportTime", "2020-12-21 12:22:13");
		param.put("prescription", prescription);
		
		String content = createFreemarkerPDF(param, "freemarker_wisdom_prescription.html");
		createPDF(content, response);
	}
	
	/**
	 * 通过Freemarker创建PDF
	 * @param param
	 * @return
	 * @throws TemplateException 
	 * @throws IOException 
	 */
	private String createFreemarkerPDF(Map<String, ?> param, String templat) throws IOException, TemplateException {
		this.initFreemarkerCfg();
		return freeMarkerRender(param, templat);
	}
	
	/**
	 * 创建PDF文件-默认A4大小
	 */
	public void createPDF(String content, Document document, HttpServletResponse response) throws IOException, DocumentException {
//		Rectangle pageSize = new Rectangle(宽, 高);
//		Document document = new Document(pageSize, 12, 12, 12, 12);
		
		// 将pdf生成到本地
//		PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(desc + 要生成的文件名));
		// 下载pdf
		PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
		document.open();
		XMLWorkerFontProvider fontImp = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
		// 注册字体
		fontImp.register(fontPath);
		XMLWorkerHelper.getInstance().parseXHtml(writer, document,new ByteArrayInputStream(content.getBytes()), null, Charset.forName("UTF-8"), fontImp);
		document.close();
	}
	
	public void createPDF(String content, HttpServletResponse response) throws IOException, DocumentException {
		createPDF(content, new Document(), response);
	}
	
    /**
     * 填充freemarket数据
     * @throws IOException 
     * @throws TemplateException 
     */
    public String freeMarkerRender(Map<?, ?> data, String htmlTmp) throws IOException, TemplateException {
    	Writer out = new StringWriter();
    	// 获取模板,并设置编码方式
		Template template = freemarkerCfg.getTemplate(htmlTmp);
		// 合并数据模型与模板
		template.process(data, out);
		out.flush();
		return out.toString();
    }
}
